package com.crm.system.service.impl.customerManager;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.crm.common.model.DhPageInfo;
import com.crm.common.util.CommonUtils;
import com.crm.model.dto.InsertCustomerCallable;
import com.crm.model.dto.InsertCustomerRawDataCallable;
import com.crm.model.dto.InsertUserCustomerCallable;
import com.crm.model.entity.customerManager.CustomerPool;
import com.crm.model.entity.sys.ImportExport;
import com.crm.model.entity.sys.UserAccount;
import com.crm.model.qo.sys.ImportFailureLogQO;
import com.crm.model.vo.customerManager.CustomerImportNewVO;
import com.crm.model.vo.customerManager.UserCustomerImportVO;
import com.crm.model.vo.sys.ImportFailureLogVO;
import com.crm.service.common.DictionaryDbService;
import com.crm.service.contactManager.ContactDbService;
import com.crm.service.contactManager.ContactInformationDbService;
import com.crm.service.customerManager.CustomerDbService;
import com.crm.service.customerManager.CustomerPoolDbService;
import com.crm.service.customerManager.CustomerRawDataDbService;
import com.crm.service.sys.ImportExportDbService;
import com.crm.service.sys.ImportFailureLogDbService;
import com.crm.service.sys.UserAccountDbService;
import com.crm.service.sys.UserInfoDbService;
import com.crm.service.sys.permissionManagement.SysCompanyDbService;
import com.crm.system.service.customerManager.CustomerImportService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.*;

/**
 * @ Author ：pym
 * @ Date   ：2021/2/23 10:35
 */
@Service
@Slf4j
public class CustomerImportServiceImpl implements CustomerImportService {
    @Autowired
    private CustomerPoolDbService customerPoolDbService;

    @Autowired
    private CustomerDbService customerDbService;

    @Autowired
    private ImportExportDbService importExportDbService;

    @Autowired
    private DictionaryDbService dictionaryDbService;

    @Autowired
    private ImportFailureLogDbService importFailureLogDbService;

    @Autowired
    private UserAccountDbService userAccountDbService;

    @Autowired
    private UserInfoDbService userInfoDbService;

    @Autowired
    private ContactDbService contactDbService;

    @Autowired
    private ContactInformationDbService contactInformationDbService;

    @Autowired
    private SysCompanyDbService sysCompanyDbService;

    @Autowired
    private CustomerRawDataDbService customerRawDataDbService;

    /**
     * 管理端客户导入
     * @Author pym
     * @param list 客户
     * @param customerPoolId 客户池Id
     * @return {@link {com.alibaba.fastjson.JSONObject}}
     */
    @Override
    public JSONObject importCustomer(List<CustomerImportNewVO> list, String customerPoolId) {
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        //返回的结果集
        JSONObject jsonObject = new JSONObject();
        //根据客户池id查询客户池信息
        CustomerPool customerPool = customerPoolDbService.selectCustomerPoolById(customerPoolId);
        //客户池容量
        int capacity = customerPool.getCapacity();
        //查询客户池客户数量
        long num = customerDbService.selectCustomerCount(customerPoolId);
        //1、查询客户池容量,判断是否超出容量
        if ((list.size() + num) < capacity) {
            int count = 100;                   //一个线程处理100条数据
            int listSize = list.size();        //数据集合大小
            int runSize = (listSize/count)+1;  //开启的线程数
            List<CustomerImportNewVO> newList = null;       //存放每个线程的执行数据
            ExecutorService executor = Executors.newCachedThreadPool();
            //创建两个个计数器
            CountDownLatch begin = new CountDownLatch(1);
            CountDownLatch end = new CountDownLatch(runSize);
            List<FutureTask<JSONObject>> taskList = new ArrayList<FutureTask<JSONObject>>();
            int startIndex;
            for (int i = 0; i < runSize ; i++) {
                //计算每个线程执行的数据
                if ((i + 1) == runSize) {
                    startIndex = (i * count);
                    int endIndex = list.size();
                    newList = list.subList(startIndex, endIndex);
                } else {
                    startIndex = (i * count);
                    int endIndex = (i + 1) * count;
                    newList = list.subList(startIndex, endIndex);
                }
                FutureTask<JSONObject> futureTask = new FutureTask(new InsertCustomerCallable(customerDbService, dictionaryDbService, customerPoolId, newList, begin, end,startIndex));
                taskList.add(futureTask);
                executor.submit(futureTask);//submit返回一个Future，代表了即将要返回的结果
            }
            // 关闭线程池
            executor.shutdown();

            jsonObject = getJsonObject(userAccount, jsonObject, taskList);
        } else {
            //已经超出客户池容量
            jsonObject.put("moreCustomerCapacity", true);
        }
        return jsonObject;
    }

    /**
     * 获取json对象
     * @Author pym
     * @Date  2021/6/7 16:41
     * @param userAccount 账号信息
     * @param jsonObject json对象
     * @param taskList
     * @return {@link {com.alibaba.fastjson.JSONObject}}
     */
    private JSONObject getJsonObject(UserAccount userAccount, JSONObject jsonObject, List<FutureTask<JSONObject>> taskList) {
        //导入数量
        int importNum = 0;
        //重复的行数
        List<Integer> repeatIdStr = new ArrayList();
        //失败行数
        List<Integer> importFailIdStr = new ArrayList();
        //客户名称或统一社会信用代码为空
        List<Integer> customerNameOrCreditCodeNull = new ArrayList();
        //账号表中未找到所有人
        List<Integer> ownerNull = new ArrayList();
        //客户名称错误
        List<Integer> wrongCustomerName = new ArrayList();
        //统一社会信用代码错误
        List<Integer> wrongUnifiedSocialCreditCode = new ArrayList();
        //客户类型和统一社会信用代码为空
        List<Integer> customerTypeAndCreditCodeNull = new ArrayList();
        //个人客户联系方式为空
        List<Integer> contactInformationEmpty = new ArrayList();
        for (int i = 0; i < taskList.size(); i++) {
            try {
                JSONObject jsonObj = taskList.get(i).get();
                // FutureTask的get方法会自动阻塞,直到获取计算结果为止
                importNum = importNum + taskList.get(i).get().getInteger("importNum");
                getLineNumberList(repeatIdStr, jsonObj, i, "repeatIdStr");
                getLineNumberList(importFailIdStr, jsonObj, i, "importFailIdStr");
                getLineNumberList(customerNameOrCreditCodeNull, jsonObj, i, "customerNameOrCreditCodeNull");
                getLineNumberList(ownerNull, jsonObj, i, "ownerNull");
                getLineNumberList(wrongCustomerName, jsonObj, i, "wrongCustomerName");
                getLineNumberList(wrongUnifiedSocialCreditCode, jsonObj, i, "wrongUnifiedSocialCreditCode");
                getLineNumberList(customerTypeAndCreditCodeNull, jsonObj, i, "customerTypeAndCreditCodeNull");
                getLineNumberList(contactInformationEmpty, jsonObj, i, "contactInformationEmpty");
            } catch (Exception e) {
                log.error("CustomerImportServiceImpl importCustomer error:", e);
            }
        }

        jsonObject.put("importCustomerNum", importNum);
        jsonObject.put("repeatIdStr", repeatIdStr);
        jsonObject.put("importFailIdStr", importFailIdStr);
        jsonObject.put("customerNameOrCreditCodeNull", customerNameOrCreditCodeNull);
        jsonObject.put("ownerNull", ownerNull);
        jsonObject.put("moreCustomerCapacity", false);
        jsonObject.put("customerTypeAndCreditCodeNull",customerTypeAndCreditCodeNull);
        jsonObject.put("wrongCustomerName",wrongCustomerName);
        jsonObject.put("wrongUnifiedSocialCreditCode",wrongUnifiedSocialCreditCode);
        jsonObject.put("contactInformationEmpty",contactInformationEmpty);
        //插入客户导入记录
        if (importNum > 0) {
            insertImportExport(userAccount, importNum);
        }
        return jsonObject;
    }

    /**
     * 获取行数集合
     * @Author pym
     * @Date  2021/6/2 14:26
     * @param jsonObject json对象
     * @param i 循环
     * @param key json对象key
     * @return {@link {java.util.List<java.lang.Integer>}}
     */
    private List<Integer> getLineNumberList(List<Integer> lineNumberList, JSONObject jsonObject, int i, String  key){
        JSONArray lineNumberArray = jsonObject.getJSONArray(key);
        for (int j = 0; j < lineNumberArray.size(); j++){
            int lineNumber = Integer.parseInt(lineNumberArray.get(j).toString());
            lineNumberList.add(lineNumber + i *100);
        }
        return lineNumberList;
    }

    /**
     * 插入导入日志
     * @Author pym
     * @Date  2021/6/7 16:10
     * @param userAccount
     * @param importNum
     * @return {@link }
     */
    private void insertImportExport(UserAccount userAccount, int importNum) {
        ImportExport importExport = new ImportExport();
        importExport.setImportExportId(CommonUtils.getGUID());
        importExport.setOperatePeopleId(userAccount.getAccountId());
        importExport.setOperateTime(new Date());
        importExport.setOperateQuantity(importNum);
        importExport.setOperateType("2");
        importExport.setOperateWay("1");
        importExportDbService.insert(importExport);
    }


    /**
     * 用户端 客户导入
     * @Author pym
     * @param list 客户
     * @param customerPoolId 客户池Id
     * @return {@link {com.alibaba.fastjson.JSONObject}}
     */
    @Override
    public JSONObject importUserCustomer(List<UserCustomerImportVO> list, String customerPoolId) {
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        //返回的结果集
        JSONObject jsonObject = new JSONObject();
        //根据客户池id查询客户池信息
        CustomerPool customerPool = customerPoolDbService.selectCustomerPoolById(customerPoolId);
        //客户池容量
        int capacity = customerPool.getCapacity();
        //查询客户池客户数量
        long num = customerDbService.selectCustomerCount(customerPoolId);
        //1、查询客户池容量,判断是否超出容量
        if ((list.size() + num) < capacity) {
            int count = 100;                   //一个线程处理100条数据
            int listSize = list.size();        //数据集合大小
            int runSize = (listSize/count)+1;  //开启的线程数
            List<UserCustomerImportVO> newList = null;       //存放每个线程的执行数据
            ExecutorService executor = Executors.newCachedThreadPool();
            //创建两个个计数器
            CountDownLatch begin = new CountDownLatch(1);
            CountDownLatch end = new CountDownLatch(runSize);
            List<FutureTask<JSONObject>> taskList = new ArrayList<FutureTask<JSONObject>>();
            int startIndex;
            for (int i = 0; i < runSize ; i++) {
                //计算每个线程执行的数据
                if ((i + 1) == runSize) {
                    startIndex = (i * count);
                    int endIndex = list.size();
                    newList = list.subList(startIndex, endIndex);
                } else {
                    startIndex = (i * count);
                    int endIndex = (i + 1) * count;
                    newList = list.subList(startIndex, endIndex);
                }
                FutureTask<JSONObject> futureTask
                        = new FutureTask(new InsertUserCustomerCallable(customerDbService, dictionaryDbService,
                        importFailureLogDbService, userAccountDbService, userInfoDbService, contactDbService,
                        contactInformationDbService, sysCompanyDbService, customerRawDataDbService,
                        customerPoolId, newList, begin, end, i));
                taskList.add(futureTask);
                executor.submit(futureTask);//submit返回一个Future，代表了即将要返回的结果
            }
            // 关闭线程池
            executor.shutdown();

            jsonObject = getJsonObject(userAccount, jsonObject, taskList);
        } else {
            //已经超出客户池容量
            jsonObject.put("moreCustomerCapacity", true);
        }
        return jsonObject;
    }

    /**
     * 客户冲突数据列表
     * @Author pym
     * @Date  2021/5/28 10:51
     * @param pageIndex -页码
     * @param pageSize -分页大小
     * @param importFailureLogQO -查询条件
     * @param sortName -排序列名字
     * @param sortOrder -排序规则(asc/desc)
     * @return {@link {com.crm.common.model.DhPageInfo<com.crm.model.vo.sys.ImportFailureLogVO>}}
     */
    @Override
    public DhPageInfo<ImportFailureLogVO> selectCustomerConflictList(Integer pageIndex, Integer pageSize,
                                                                       ImportFailureLogQO importFailureLogQO,
                                                                       String sortName, String sortOrder) {
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        List<ImportFailureLogVO> customerConflictList = new ArrayList<ImportFailureLogVO>();
        if (pageIndex != null && pageSize != null) {
            PageHelper.startPage(pageIndex, pageSize);
        }
        if (CommonUtils.isAdmin(userAccount.getUserId())) { //超级管理员
            customerConflictList = importFailureLogDbService.selectCustomerConflictList(importFailureLogQO, null);
        } else {
            customerConflictList = importFailureLogDbService.selectCustomerConflictList(importFailureLogQO, userAccount.getAccountId());
        }
        PageInfo<ImportFailureLogVO> pageInfo = new PageInfo<ImportFailureLogVO>(customerConflictList);
        return new DhPageInfo<ImportFailureLogVO>(pageInfo, customerConflictList);
    }

    /**
     * 导入失败数据列表
     * @Author pym
     * @Date  2021/5/28 13:59
     * @param pageIndex -页码
     * @param pageSize -分页大小
     * @param importFailureLogQO -查询条件
     * @param sortName -排序列名字
     * @param sortOrder -排序规则(asc/desc)
     * @return {@link {com.crm.common.model.DhPageInfo<com.crm.model.vo.sys.ImportFailureLogVO>}}
     */
    @Override
    public DhPageInfo<ImportFailureLogVO> selectImportFailedDataList(Integer pageIndex, Integer pageSize,
                                                                     ImportFailureLogQO importFailureLogQO,
                                                                     String sortName, String sortOrder) {
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        List<ImportFailureLogVO> importFailedDataList = new ArrayList<ImportFailureLogVO>();
        if (pageIndex != null && pageSize != null) {
            PageHelper.startPage(pageIndex, pageSize);
        }
        if (CommonUtils.isAdmin(userAccount.getUserId())) { //超级管理员
            importFailedDataList = importFailureLogDbService.selectImportFailedDataList(importFailureLogQO, null);
        } else {
            importFailedDataList = importFailureLogDbService.selectImportFailedDataList(importFailureLogQO, userAccount.getAccountId());
        }
        PageInfo<ImportFailureLogVO> pageInfo = new PageInfo<ImportFailureLogVO>(importFailedDataList);
        return new DhPageInfo<ImportFailureLogVO>(pageInfo, importFailedDataList);
    }

    /**
     * 导入客户原始数据
     * @Author pym
     * @Date  2021/7/13 11:45
     * @param list 客户集合
     * @return {@link {com.alibaba.fastjson.JSONObject}}
     */
    @Override
    public JSONObject importCustomerRawData(List<UserCustomerImportVO> list) {
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        //返回的结果集
        JSONObject jsonObject = new JSONObject();
        int count = 100;                   //一个线程处理100条数据
        int listSize = list.size();        //数据集合大小
        int runSize = (listSize/count)+1;  //开启的线程数
        List<UserCustomerImportVO> newList = null;       //存放每个线程的执行数据
        ExecutorService executor = Executors.newCachedThreadPool();
        //创建两个个计数器
        CountDownLatch begin = new CountDownLatch(1);
        CountDownLatch end = new CountDownLatch(runSize);
        List<FutureTask<JSONObject>> taskList = new ArrayList<FutureTask<JSONObject>>();
        int startIndex;
        for (int i = 0; i < runSize ; i++) {
            //计算每个线程执行的数据
            if ((i + 1) == runSize) {
                startIndex = (i * count);
                int endIndex = list.size();
                newList = list.subList(startIndex, endIndex);
            } else {
                startIndex = (i * count);
                int endIndex = (i + 1) * count;
                newList = list.subList(startIndex, endIndex);
            }
            FutureTask<JSONObject> futureTask
                    = new FutureTask(new InsertCustomerRawDataCallable(customerRawDataDbService, newList, begin, end, i));
            taskList.add(futureTask);
            executor.submit(futureTask);//submit返回一个Future，代表了即将要返回的结果
        }
        //导入数量
        int importNum = 0;
        //失败行数
        List<Integer> importFailIdStr = new ArrayList();
        for (int i = 0; i < taskList.size(); i++) {
            try {
                //导入数量
                importNum = importNum + taskList.get(i).get().getInteger("importNum");

                //失败行数
                importFailIdStr = getNumList(taskList, importFailIdStr, i, "importFailIdStr");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 关闭线程池
        executor.shutdown();
        jsonObject.put("importNum", importNum);
        jsonObject.put("importFailIdStr", importFailIdStr);
        return jsonObject;
    }

    /**
     * 获取行数
     * @Author pym
     * @Date  2021/7/13 14:07
     * @param taskList
     * @param list 行数集合
     * @param i 循环
     * @param key json对象key
     * @return {@link {java.util.List<java.lang.Integer>}}
     */
    private List<Integer> getNumList(List<FutureTask<JSONObject>> taskList, List<Integer> list, int i , String key) throws Exception {
        JSONArray jsonArray = taskList.get(i).get().getJSONArray(key);
        if (jsonArray != null && jsonArray.size() > 0) {
            for (int j = 0; j < jsonArray.size(); j++) {
                list.add(Integer.parseInt(jsonArray.get(j).toString()));
            }
        }
        return list;
    }

}
